<template>
	<view>
		<view class="TUI-message-input-container" :style="{ bottom: inputheight + 'px', paddingBottom: displayFlag == 'emoji' ? '0rpx' : 'env(safe-area-inset-bottom)' }">
			<view class="TUI-message-input">
				<view class="TUI-message-input-flex" :style="{ alignItems: isOverOneLine ? ' flex-end' : 'center' }">
					<view class="input_left">
						<image class="TUI-icon" @tap="switchAudio" :src="isAudio ? '/static/timstatic/assets/keyboard.svg' : '/static/timstatic/assets/audio.svg'"></image>
					</view>
					<view class="TUI-message-input-main">
						<view v-show="!isAudio" class="TUI-message-input-area">
							<textarea
								id="messageInput"
								class="text-preview"
								:adjust-position="false"
								confirm-type="send"
								:show-confirm-bar="false"
								type="text"
								placeholder="说点什么呢~"
								v-model="inputText"
								disable-default-padding
								cursor-spacing="0"
								auto-height
								:maxlength="-1"
								:focus="isFocus"
								@input="onInput"
								@blur="onblur"
								@confirm="sendTextMessage"
								@longpress="handleTextareaLongPress"
								@keyboardheightchange="keyboardheightchange"
							/>
						</view>
						<view v-show="isAudio" class="TUI-message-input-area" @longpress="handleLongPress" @touchmove="handleTouchMove" @touchend="handleTouchEnd">
							<view class="texts">
								{{ text }}
							</view>
						</view>
					</view>
					<view class="input_right">
						<view class="TUI-message-input-functions">
							<image
								v-if="displayFlag === 'emoji'"
								style="margin-right: 15rpx"
								class="TUI-icon"
								@tap="handleEmoji"
								src="/static/timstatic/assets/keyboard.svg"
							></image>
							<image v-else style="margin-right: 15rpx" class="TUI-icon" @tap="handleEmoji" src="/static/timstatic/assets/face-emoji.svg"></image>
							<view @tap="handleExtensions">
								<image class="TUI-icon" src="/static/timstatic/assets/more.svg"></image>
							</view>
						</view>
					</view>
				</view>
				<view class="quote" v-if="isQuote">
					<view class="quote-row">
						<!-- 自定义 -->
						<view class="" v-if="quoteSource.type == 'TIMCustomElem'">{{ quoteSource.nick }}：{{ quoteSource.payload.data }}</view>
						<!-- 文字 -->
						<view class="" v-if="quoteSource.type == 'TIMTextElem'">{{ quoteSource.nick }}：{{ quoteSource.payload.text }}</view>
						<!-- 图片 -->
						<view class="" v-if="quoteSource.type == 'TIMImageElem'">{{ quoteSource.nick }}：[图片]</view>
						<!-- 视频 -->
						<view class="" v-if="quoteSource.type == 'TIMVideoFileElem'">{{ quoteSource.nick }}：[视频]</view>
						<!-- 语音 -->
						<view class="" v-if="quoteSource.type == 'TIMSoundElem'">{{ quoteSource.nick }}：[语音]{{ quoteSource.payload.second }}</view>
					</view>
					<view class="quote-icon" @click="cancelQuote">
						<image
							class="img"
							src=""
							mode="aspectFill"
						></image>
					</view>
				</view>
			</view>
			<view v-if="displayFlag === 'emoji'" class="TUI-Emoji-area" :class="{ active: displayFlag === 'emoji' }">
				<TUI-Emoji @enterEmoji="appendMessage" :hasContent="!!inputText.trim()" @delete="handleDeleteChar" @send="sendTextMessage"></TUI-Emoji>
			</view>
			<view v-if="displayFlag === 'extension'" class="TUI-Extensions">
				<view class="TUI-Extension-slot" @tap="handleSendPicture">
					<image class="TUI-Extension-icon" src="/static/timstatic/assets/take-photo.svg"></image>
					<view class="TUI-Extension-slot-name">拍摄照片</view>
				</view>
				<view class="TUI-Extension-slot" @tap="handleSendImage">
					<image class="TUI-Extension-icon" src="/static/timstatic/assets/send-img.svg"></image>
					<view class="TUI-Extension-slot-name">发送图片</view>
				</view>
				<view class="TUI-Extension-slot" @tap="handleShootVideo">
					<image class="TUI-Extension-icon" src="/static/timstatic/assets/take-video.svg"></image>
					<view class="TUI-Extension-slot-name">拍摄视频</view>
				</view>
				<view class="TUI-Extension-slot" @tap="handleSendVideo">
					<image class="TUI-Extension-icon" src="/static/timstatic/assets/send-video.svg"></image>
					<view class="TUI-Extension-slot-name">发送视频</view>
				</view>
			</view>
		</view>
		<view class="record-modal" v-if="popupToggle" @longpress="handleLongPress" @touchmove="handleTouchMove" @touchend="handleTouchEnd">
			<view class="wrapper">
				<view class="modal-loading"></view>
			</view>
			<view class="modal-title">{{ title }}</view>
		</view>
	</view>
</template>

<script>
import TUIEmoji from '../message-elements/emoji/index';
import { emojiName } from '@/chat/base/emojiMap.js';
export default {
	data() {
		return {
			inputText: '',
			displayFlag: '',
			isAudio: false,
			startPoint: 0,
			popupToggle: false,
			isRecording: false,
			canSend: true,
			text: '按住说话',
			title: ' ',
			recordTime: 0,
			recordTimer: null,
			inputheight: 0,
			isQuote: false,
			isFocus: false,
			quoteSource: {},
			cursorPos: 0,
			ctrlPressed: false,
			isOverOneLine: false
		};
	},

	components: {
		TUIEmoji
	},
	props: {
		conversation: {
			type: Object,
			default: () => {}
		}
	},

	beforeMount() {
		// 加载声音录制管理器
		this.recorderManager = uni.getRecorderManager();
		this.recorderManager.onStop((res) => {
			clearInterval(this.recordTimer);
			// 兼容 uniapp 打包app，duration 和 fileSize 需要用户自己补充
			// 文件大小 ＝ (音频码率) x 时间长度(单位:秒) / 8
			let msg = {
				duration: res.duration ? res.duration : this.recordTime * 1000,
				tempFilePath: res.tempFilePath,
				fileSize: res.fileSize ? res.fileSize : ((48 * this.recordTime) / 8) * 1024
			};
			uni.hideLoading();
			// 兼容 uniapp 语音消息没有duration
			if (this.canSend) {
				if (msg.duration < 1000) {
					uni.showToast({
						title: '录音时间太短',
						icon: 'none'
					});
				} else {
					// res.tempFilePath 存储录音文件的临时路径
					const message = uni.$TUIKit.createAudioMessage({
						to: this.getToAccount(),
						conversationType: this.conversation.type,
						payload: {
							file: msg
						}
					});
					this.$sendTIMMessage(message);
				}
			}

			this.startPoint = 0;
			this.popupToggle = false;
			this.isRecording = false;
			this.canSend = true;
			this.title = ' ';
			this.text = '按住说话';
		});
	},

	methods: {
		closess() {
			this.isQuote = false;
			this.displayFlag = '';
		},
		// 处理删除最后一个字符
		handleDeleteChar() {
			if (!this.inputText) return;
			// 从末尾遍历，查找是否以某个表情标识结尾
			// 优化性能：优先检查最长的表情（避免短表情误判，如[困]和[困困]）
			const sortedEmojis = [...emojiName].sort((a, b) => b.length - a.length);
			for (const emoji of sortedEmojis) {
				// 判断当前内容是否以该表情结尾
				if (this.inputText.endsWith(emoji)) {
					// 是表情，删除整个表情
					this.inputText = this.inputText.slice(0, -emoji.length);
					return; // 找到后立即退出
				}
			}
			// 不是表情，删除最后一个字符
			this.inputText = this.inputText.slice(0, -1);
		},
		onInput(e) {
			this.cursorPos = e.detail.cursor;
			this.$nextTick(() => {
				const query = uni.createSelectorQuery().in(this);
				query
					.select('.text-preview')
					.boundingClientRect((data) => {
						if (data) {
							// 如果元素高度大于单行高度，说明超出一行
							this.isOverOneLine = data.height > 35; // 根据实际行高调整
						}
					})
					.exec();
			});
		},
		onblur(e) {
			this.cursorPos = e.detail.cursor;
			this.isFocus = false;
		},
		handleTextareaLongPress() {
			// 获取当前输入框内容和光标位置
			const currentText = this.inputText || '';
			const cursor = this.cursorPos; // 从onInput中同步的光标位置
			// 在光标位置插入换行符
			const start = currentText.substring(0, cursor);
			const end = currentText.substring(cursor);
			this.inputText = start + '\n' + end;

			// 计算新光标位置（原位置+1，跳过换行符）
			const newCursorPos = cursor + 1;

			// 确保DOM更新后调整光标并保持焦点
			this.$nextTick(() => {
				this.cursorPos = newCursorPos;
				// 强制保持焦点（微信小程序需通过selectComponent调用focus）
				const textarea = this.selectComponent('.TUI-message-input-area');
				if (textarea && typeof textarea.focus === 'function') {
					textarea.focus();
				}
				this.isFocus = true;
			});
		},
		//引用消息
		quote(item) {
			// 删除嵌套引用
			const itemx = JSON.parse(JSON.stringify(item));
			this.isQuote = true;
			this.quoteSource = itemx;
		},
		cancelQuote() {
			this.isQuote = false;
		},
		fun(type, msg) {
			let obj = {};
			if (type == 'quote') {
				obj.ID = msg.ID;
				obj.type = msg.type;
				obj.nick = msg.nick;
				obj.payload = msg.payload;
			}
			return JSON.stringify(obj);
		},
		sendTextMessage(msg, flag) {
			const to = this.getToAccount();
			const text = flag ? msg : this.inputText;
			const message = uni.$TUIKit.createTextMessage({
				to,
				conversationType: this.conversation.type,
				payload: {
					text
				},
				cloudCustomData: this.isQuote ? this.fun('quote', this.quoteSource) : ''
			});
			this.inputText = '';
			this.$sendTIMMessage(message);
		},
		$sendTIMMessage(message) {
			this.$emit('sendMessage', {
				detail: {
					message
				}
			});
			uni.$TUIKit.sendMessage(message);
			this.isQuote = false;
			this.displayFlag = '';
		},
		switchAudio() {
			uni.getSetting({
				success: (res) => {
					if (!res.authSetting['scope.record']) {
						uni.authorize({
							scope: 'scope.record',
							success: () => {
								// 用户已经同意小程序使用录音功能，后续调用 wx.startRecord 接口不会弹窗询问
								uni.openSetting({
									success: (response) => {
										if (response.authSetting['scope.record']) {
											this.isAudio = !this.isAudio;
											this.text = '按住说话';
										}
									}
								});
							},
							fail: (err) => {
								console.log(err);
							}
						});
					} else {
						// 已授权，直接获取位置信息
						this.isAudio = !this.isAudio;
						this.text = '按住说话';
					}
				}
			});
		},
		handleLongPress(e) {
			this.recorderManager.start({
				duration: 60000,
				sampleRate: 44100,
				numberOfChannels: 1,
				encodeBitRate: 192000,
				format: 'aac'
			});
			this.startPoint = e.touches[0];
			this.title = '正在录音';
			this.isRecording = true;
			this.popupToggle = true;
			this.recordTime = 0;
			this.recordTimer = setInterval(() => {
				this.recordTime++;
			}, 1000);
		},

		// 录音时的手势上划移动距离对应文案变化
		handleTouchMove(e) {
			if (this.isRecording) {
				if (this.startPoint.clientY - e.touches[e.touches.length - 1].clientY > 100) {
					this.text = '抬起停止';
					this.title = '松开手指，取消发送';
					this.canSend = false;
				} else if (this.startPoint.clientY - e.touches[e.touches.length - 1].clientY > 20) {
					this.text = '抬起停止';
					this.title = '上划可取消';
					this.canSend = true;
				} else {
					this.text = '抬起停止';
					this.title = '正在录音';
					this.canSend = true;
				}
			}
		},

		// 手指离开页面滑动
		handleTouchEnd() {
			this.isRecording = false;
			this.popupToggle = false;
			uni.hideLoading();
			this.recorderManager.stop();
		},
		handleEmoji() {
			let targetFlag = 'emoji';
			if (this.displayFlag === 'emoji') {
				targetFlag = '';
				this.$nextTick(() => {
					// 强制保持焦点（微信小程序需通过selectComponent调用focus）
					const textarea = this.selectComponent('.TUI-message-input-area');
					if (textarea && typeof textarea.focus === 'function') {
						textarea.focus();
					}
					this.isFocus = true;
				});
			} else {
			}
			this.displayFlag = targetFlag;
		},
		handleExtensions() {
			let targetFlag = 'extension';
			if (this.displayFlag === 'extension') {
				targetFlag = '';
			}
			this.displayFlag = targetFlag;
			this.$nextTick(() => {
				// 获取当前页面的选择器上下文
				const query = uni.createSelectorQuery().in(this);
				query
					.select('#messageInput') // 用id选择器替代ref
					.fields({ node: true }, (res) => {
						if (res.node) {
							// 调用输入框的focus方法
							res.node.focus();
						}
					})
					.exec();
			});
		},

		handleSendPicture() {
			this.sendImageMessage('camera');
		},

		handleSendImage() {
			this.sendImageMessage('album');
		},
		sendImageMessage(type) {
			uni.chooseImage({
				sourceType: [type],
				count: 1,
				success: (res) => {
					if (res) {
						const message = uni.$TUIKit.createImageMessage({
							to: this.getToAccount(),
							conversationType: this.conversation.type,
							payload: {
								file: res
							},
							onProgress: (percent) => {
								message.percent = percent;
							}
						});
						this.$sendTIMMessage(message);
					}
				}
			});
		},

		handleShootVideo() {
			this.sendVideoMessage('camera');
		},

		handleSendVideo() {
			this.sendVideoMessage('album');
		},
		sendVideoMessage(type) {
			uni.chooseVideo({
				sourceType: [type],
				maxDuration: 60,
				camera: 'back',
				success: (res) => {
					if (res) {
						const message = uni.$TUIKit.createVideoMessage({
							to: this.getToAccount(),
							conversationType: this.conversation.type,
							payload: {
								file: res
							},
							onProgress: (percent) => {
								message.percent = percent;
							}
						});
						this.$sendTIMMessage(message);
					}
				}
			});
		},
		appendMessage(e) {
			this.inputText = this.inputText + e.detail.message;
		},
		getToAccount() {
			if (!this.conversation || !this.conversation.conversationID) {
				return '';
			}
			switch (this.conversation.type) {
				case 'C2C':
					return this.conversation.conversationID.replace('C2C', '');
				case 'GROUP':
					return this.conversation.conversationID.replace('GROUP', '');
				default:
					return this.conversation.conversationID;
			}
		},
		keyboardheightchange(e) {
			if (e.detail.height == 0) {
				this.inputheight = 0;
			} else {
				this.displayFlag = '';
				this.inputheight = e.detail.height - uni.getStorageSync('safeAreaInsets').bottom;
			}
		}
	}
};
</script>
<style>
@import './index.css';
</style>
